# -*- encoding: utf-8 -*-
'''
@File		:	proxy_server.py
@Time		:	2024/01/05 15:45:00
@Author		:	dan
@Description:	代理服务器，通过matter命令行开启代理服务
'''

import socket
import time
import selectors
import threading

class UdpServer:


    @property
    def started(self) -> bool:
        ''' 
        线程是否已开始
        '''
        
        return self.__running

    '''
    代理服务器，监听指定的端口，接收主测试机的指令
    '''
    def __init__(self, port : int = 6666, callback = None , quiet : bool=False) -> None:
        ''' 
        Parameters
        ----------
        port : int = 6666 代理服务器监听的端口

        callback : function[socket.socket, str] 监听接收的回调
        
        Return
        ----------
        '''

        self.__port = port
        self.__socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        # self.__socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 3)
        self.__started = False
        self.__selector = selectors.DefaultSelector()
        self.__last = {}
        self.__quiet = quiet
        self.__socket.settimeout(1)
        self.__callback = callback

        self.__thread = threading.Thread(target=self.run)
        self.__running = False
        pass


    def __accept(self, sock : socket.socket, mask):
        ''' socket连接的回调
        Parameters
        ----------
        sock 也就是 self.__socket

        mask 
        
        Return
        ----------
        '''
        
        data, conn = sock.recvfrom(1024)  # Should be ready
        print(f'    来自 {conn[0]}:{conn[1]}， 接收 {data}')
        if self.__callback:
            self.__callback(sock, conn, data)


    def start(self) -> None:
        ''' 开始监听
        
        Parameters
        ----------
        
        
        Returns
        -------
        None
        
        '''
        self.__running = True
        self.__thread.start()
        pass

    def close(self) -> None:
        ''' 结束监听
        
        Parameters
        ----------
        
        
        Returns
        -------
        None
        
        '''
        self.__running = False
        pass


    def run(self) -> None:
        ''' 开启代理服务器
        
        Parameters
        ----------
        
        
        Returns
        -------
        None
        
        '''
        if self.__started:
            return;
        self.__started = True

        sock = self.__socket
        sock.bind(('0.0.0.0', self.__port))
        # sock.listen(2)
        sock.setblocking(False)
        sel = self.__selector
        sel.register(sock, selectors.EVENT_READ, self.__accept)
        if not self.__quiet:
            print(f"代理服务器开始监听，监听端口{self.__port}\n")
        while self.__running:
            try:  
                events = sel.select()
                for key, mask in events:
                    callback = key.data
                    callback(key.fileobj, mask)
            except Exception as e:  #捕捉错误
                print (e)
                time.sleep(4)  #每4秒打印一个捕捉到的错误

        if not self.__quiet:
            print(f"代理服务器结束监听\n")
        sock.close()
        sel.close()
        pass




if __name__ == '__main__':
    def response(sock : socket.socket, conn, data):
        sock.sendto(bytes(str(data) + "_response", encoding='utf8'), (conn[0], 7777))
    server = UdpServer(callback=response)
    server.start()
    time.sleep(1000)